Skip to main content

06 ADC实验

光照/温度采集实验 麦克风实验

up的视频讲解: https://space.bilibili.com/1455872040

up视频里的实验代码: 👣ADC实验代码、

1 🌡️ 光/热传感器-光照/温度采集实验​

1.1 实验连接​

图片

1.2 实验原理​

图片
  • 温度采集实验中, 通过NTC热敏电阻将温度转化为电压信号, 再通过ADC将电压信号转化为具体的数值

  • 光照采集实验中, 通过光敏电阻将光强转化为电压信号, 再通过ADC将电信号转化为具体的数值

1.3 CubeMX配置​

按PPT接线将AO接PA1,选择ADC1_IN1模拟输入。ADC1单通道、右对齐、Scan关闭、Continuous关闭、Software Start;开启ADC1_2中断。首次使用前执行HAL_ADCEx_Calibration_Start。

72 MHz系统下设置ADC时钟为PCLK2/6,即12 MHz;光敏/热敏分压源先选较长采样时间239.5 cycles。USART1使用PA9发送,115200、8N1,与串口助手一致。

图片
图片
图片

1.4 实验代码​

全局​

#include <stdio.h>

uint16_t adc_val = 0;
uint8_t flag = 0;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
adc_val = HAL_ADC_GetValue(&hadc1);
flag = 1;
}
}

main()​

	HAL_ADC_Start_IT(&hadc1);

while(1)​

		if(flag == 1)
{
char buf[64] = {0};
sprintf(buf,"adc_val=%d V_AO=%f\r\n",adc_val,adc_val/4096.0f*3.3f);
HAL_UART_Transmit(&huart1,buf,strlen(buf),1000);
flag = 0;
HAL_ADC_Start_IT(&hadc1);
}

1.5 温度/光照 计算​

图片

1.6 温度计算代码​

//==================== NTC热敏电阻参数(B3950‑10K) ====================
#include "math.h"
#define NTC_R_FIX 10000.0f //电路上拉固定电阻R1=10k
#define R25 10000.0f //25℃标称NTC电阻
#define T25 298.15f //25℃开尔文
#define B 3950.0f //B值
#define ADC_MAX 4095.0f
/**
* @brief NTC热敏电阻B值模型计算温度
* @param adc_val: ADC原始采样值,范围0~4095
* @retval 温度值,单位℃
* @note 硬件电路:VCC →10k固定电阻 →AO采样点 →NTC →GND
*/
float NTC_GetTemperature(uint16_t adc_val)
{
// 根据ADC分压换算NTC当前实时电阻
float R_ntc = NTC_R_FIX * adc_val / (ADC_MAX - adc_val);
// NTC B值公式,计算开尔文温度
float invT = 1.0f / T25 + (1.0f / B) * logf(R_ntc / R25);
float T_K = 1.0f / invT;
// 开尔文温度转换为摄氏温度
float T_C = T_K - 273.15f;
return T_C;
}

1.7 光照计算代码​

//==================== GL5528光敏电阻参数 ====================
#include "math.h"
#define LDR_R_FIX 10000.0f //电路上拉固定电阻R1=10k
#define LDR_R10 10000.0f //10Lux时光敏电阻阻值10kΩ
#define LDR_GAMMA 0.7f //GL5528伽马值γ
#define ADC_MAX 4095.0f

/**
* @brief GL5528光敏电阻计算光照度
* @param adc_val: ADC原始采样值,范围0~4095
* @retval 光照度,单位Lux(勒克斯),仅相对值,非计量级精度
* @note 硬件电路:VCC →10k固定电阻 →AO采样点 →LDR →GND
* 公式: Lux = 10 * pow(R10 / Rldr, 1/gamma)
*/
float LDR_GetLux(uint16_t adc_val)
{
// 根据ADC分压换算光敏电阻当前实时电阻
float R_ldr = LDR_R_FIX * adc_val / (ADC_MAX - adc_val);

// 光敏电阻照度‑电阻经验公式,计算环境光照度Lux
float lux = 10.0f * powf( LDR_R10 / R_ldr, 1.0f / LDR_GAMMA );

return lux;
}

2 🎙️ 麦克风- 音频采集实验​

2.1 实验连接​

图片

2.2 实验原理​

  • 音频采集实验中, 通过麦克风将声音信号转化为电压信号

  • 再通过ADC将电信号转化为具体的数值

  • 最后再通过UP写的串口助手画出波形

2.3 CubeMX配置​

麦克风OUT接PA1/ADC1_IN1,ADC1单通道、右对齐、Scan关闭、Continuous关闭,外部触发选择TIM3 TRGO;开启ADC1_2中断。

为配合下面逐点文本发送的演示,先用1 kHz采样:TIM3时钟72 MHz,PSC=71、ARR=999,TRGO选择Update Event。ADC时钟12 MHz,采样时间可从55.5 cycles开始。先启动ADC等待触发,再启动TIM3。要做8 kHz音频与FFT,请使用后续DMA实验,不要直接提高本段逐点阻塞打印的速率。

2.4 实验代码​

全局​

#include <stdio.h>

uint16_t adc_val = 0;
uint8_t flag = 0;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
adc_val = HAL_ADC_GetValue(&hadc1);
flag = 1;
}
}

main()​

	HAL_ADC_Start_IT(&hadc1);
HAL_TIM_Base_Start(&htim3);

while(1)​

		if(flag == 1)
{
char buf[64] = {0};
sprintf(buf,"%d\r\n",adc_val);
HAL_UART_Transmit(&huart1,buf,strlen(buf),1000);
flag = 0;
}

✅换算与采样的边界​

NTC公式依赖上方固定电阻、下方NTC的分压接法。上下位置交换时必须重新推导。码值0或4095可能意味着开短路、饱和或边界输入,视频原代码未包含端点保护;工程化处理的边界检查另见补充说明。

光敏电阻的R10与gamma是示例参数,批次与环境差异很大,未校准时只能观察相对变化,不能当作可靠照度计。

逐点中断加阻塞打印会漏掉连续采样事件,即使给flag加volatile也不能解决带宽问题。麦克风演示先看低速波形,完整音频处理改用FFT章节的定时器+DMA方案。